﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TByte.XnaHelper
{
    public class Line
    {
        #region Fields
        //The points
        Vector2 pointA;
        Vector2 pointB;

        
        Vector2 minBounds;
        Vector2 maxBounds;

        //As in Y = dY/dX * x + constant
        float dYdX;
        float constant;
        float dX;
        #endregion

        #region Methods
        public bool Intersects(Line other)
        {
            if (this.dX == 0)
            {
                //this line is vertical
                if (other.dX == 0)
                {
                    //Lines are both vertical
                    if (this.pointA.X == other.pointA.X)
                    {
                        return true;
                    }
                }
                else
                {
                    if (other.IsOnDomain(this.PointA.X) && this.IsOnRange(other.Value(this.pointA.X)))
                        return true;
                }
            }
            else if (other.dX == 0)
            {
                //other line is vertical
                if (this.IsOnDomain(other.pointA.X) && other.IsOnRange(this.Value(other.PointA.X)))
                    return true;
            }
            else if (this.dYdX == other.dYdX)
            {
                //The lines are paralel
                //Only intersect if overlap
                if (this.Value(1) == other.Value(1))
                {
                    //Values in 1 are the same
                    return true;
                }
            }
            else
            {
                //There is an intersect somewhere
                float x = (this.pointA.X * this.dYdX - this.pointA.Y - other.PointA.X * other.dYdX + other.PointA.Y) / (this.dYdX - other.dYdX);

                //If x is on the domain of both
                if (this.IsOnDomain(x) && other.IsOnDomain(x))
                {
                    return true;
                }
            }
            //No intersect
            return false;
        }
        float Value(float x)
        {
            return dYdX * x + constant;
        }
        public bool IsOnRange(float y)
        {
            if (y >= minBounds.Y && y <= maxBounds.Y)
            {
                return true;
            }
            return false;
        }
        public bool IsOnDomain(float x)
        {
            if (x >= minBounds.X && x <= maxBounds.X)
            {
                return true;
            }
            return false;
        }
        void Recalculate()
        {
            dX = pointB.X - pointA.X;
            dYdX = (pointB.Y - pointA.Y) / dX;
            constant = pointA.Y - pointA.X * dYdX;

            minBounds = new Vector2(Math.Min(pointA.X, pointB.X), Math.Min(pointA.Y, pointB.Y));
            maxBounds = new Vector2(Math.Max(pointA.X, pointB.X), Math.Max(pointA.Y, pointB.Y));
        }
        public void draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Manager.dummyTexture, new Vector2(PointA.X, PointA.Y), null, Color.Red,
                         (float)Math.Atan2(PointB.Y - pointA.Y, PointB.X - PointA.X),
                         new Vector2(0f, 0.5f),
                         new Vector2(Length, 4f),
                         SpriteEffects.None, 0f);
        }
        #endregion

        #region Constructors
        public Line(Vector2 A, Vector2 B)
        {
            pointA = A;
            pointB = B;

            Recalculate();
        }
        #endregion

        #region Properties
        public Vector2 PointA { get { return pointA; } set { pointA = value; } }
        public Vector2 PointB { get { return pointB; } set { pointB = value; } }
        public float Length { get { return (pointA - pointB).Length(); } }
        #endregion
    }
}
